#if defined(_MSC_VER)
#pragma once
#endif

#ifndef LM_TEXTURE_CHECKERBOARD_H
#define LM_TEXTURE_CHECKERBOARD_H

#include "../core/lm.h"
#include "../core/texture.h"
#include "../core/textureMap.h"
#include "../core/intersection.h"

template<class T> class Checkerboard : public Texture<T> {
public:
	Checkerboard(Reference<TextureMap> m, Reference<Texture<T>> t1, Reference<Texture<T>> t2, const string &aa) {
		mapping = m;
		tex1 = t1;
		tex2 = t2;
		if(aa == "none")
			aaMethod = NONE;
		else if(aa == "closedform")
			aaMethod = CLOSEDFORM;
		else {
			Warning("Use default point sample for checkerboard texture\n");
			aaMethod  = NONE;
		}
	}
	~Checkerboard() {
		mapping = NULL;
		tex1 = NULL;
		tex2 = NULL;
	}
	T Evaluate(const Intersection &isect) const {
		float s, t, dsdx, dtdx, dsdy, dtdy;
		mapping->Map(isect, &s, &t, &dsdx, &dtdx, &dsdy, &dtdy);
		if(aaMethod == CLOSEDFORM) {
			float ds = max(fabsf(dsdx), fabsf(dsdy));
			float dt = max(fabsf(dtdx), fabsf(dtdy));
			float s0 = s - ds, s1 = s + ds;
			float t0 = t - dt, t1 = t + dt;
			if(Floor2Int(s0) == Floor2Int(s1) && Floor2Int(t0) == Floor2Int(t1)) {
				int is = Floor2Int(s);
				int it = Floor2Int(t);
				if( (is + it) % 2 == 0)
				return tex1->Evaluate(isect);
				else return tex2->Evaluate(isect);
			}
			#define BUMPINT(x) \
				(Floor2Int((x)/2) + \
				2.f * max((x/2)-Floor2Int(x/2) - .5f, 0.f))
			float sint = (BUMPINT(s1) - BUMPINT(s0)) / (2.f * ds);
			float tint = (BUMPINT(t1) - BUMPINT(t0)) / (2.f * dt);
			float area2 = sint + tint - 2.f * sint * tint;
			if(ds > 1.f || dt > 1.f)
				area2 = 0.5f;
			return (1.f - area2) * tex1->Evaluate(isect) + area2 * tex2->Evaluate(isect);
			
		}
		
		// aaMethod == NONE
		int is = Floor2Int(s);
		int it = Floor2Int(t);
		if( (is + it) % 2 == 0)
			return tex1->Evaluate(isect);
		else return tex2->Evaluate(isect);
	}
private:
	Reference<TextureMap> mapping;
	Reference<Texture<T>> tex1, tex2;
	//enum { NONE, SUPERSAMPLE, CLOSEDFORM } aaMethod;
	enum { NONE, CLOSEDFORM } aaMethod;
};

#endif	// LM_TEXTURE_CHECKERBOARD_H